home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Very Best of Atari Inside
/
The Very Best of Atari Inside 1.iso
/
mint
/
mint110s
/
timeout.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-16
|
5KB
|
233 lines
/*
Copyright 1990,1991,1992 Eric R. Smith.
Copyright 1992,1993 Atari Corporation.
All rights reserved.
*/
#include "mint.h"
/*
* We initialize proc_clock to a very large value so that we don't have
* to worry about unexpected process switches while starting up
*/
short proc_clock = 0x7fff;
/* used by filesystems for time/date stamps; updated once per second */
short timestamp, datestamp;
extern short in_kernel; /* in main.c */
static void unnapme P_((PROC *));
/*
* addtimeout(long delta, void (*func)()): schedule a timeout for the current
* process, to take place in "delta" milliseconds. "func" specifies a
* function to be called at that time; the function is passed as a parameter
* the process for which the timeout was specified (i.e. the value of
* curproc at the time addtimeout() was called; note that this is probably
* *not* the current process when the timeout occurs).
*/
TIMEOUT *tlist;
#define newtimeout() (TIMEOUT *)kmalloc(SIZEOF(TIMEOUT))
#define disposetimeout(t) kfree(t)
TIMEOUT * ARGS_ON_STACK
addtimeout(delta, func)
long delta;
void (*func) P_((PROC *));
{
TIMEOUT *t, **prev, *cur;
t = newtimeout();
/* BUG: we should have some fallback mechanism for timeouts when the
kernel memory is exhausted
*/
assert(t);
t->proc = curproc;
t->func = func;
cur = tlist;
prev = &tlist;
while (cur) {
if (cur->when >= delta) {
cur->when -= delta;
t->next = cur;
t->when = delta;
*prev = t;
return t;
}
delta -= cur->when;
prev = &cur->next;
cur = cur->next;
}
assert(delta >= 0);
t->when = delta;
t->next = cur;
*prev = t;
return t;
}
/*
* cancelalltimeouts(): cancels all pending timeouts for the current
* process
*/
void ARGS_ON_STACK
cancelalltimeouts()
{
TIMEOUT *cur, **prev, *old;
long delta;
cur = tlist;
prev = &tlist;
while (cur) {
if (cur->proc == curproc) {
delta = cur->when;
old = cur;
*prev = cur = cur->next;
if (cur) cur->when += delta;
disposetimeout(old);
}
else {
prev = &cur->next;
cur = cur->next;
}
}
}
/*
* Cancel a specific timeout. If the timeout isn't on the list, or isn't
* for this process, we do nothing; otherwise, we cancel the time out
* and then free the memory it used. *NOTE*: it's very possible (indeed
* likely) that "this" was already removed from the list and disposed of
* by the timeout processing routines, so it's important that we check
* for it's presence in the list and do absolutely nothing if we don't
* find it there!
*/
void ARGS_ON_STACK
canceltimeout(this)
TIMEOUT *this;
{
TIMEOUT *cur, **prev;
prev = &tlist;
for (cur = tlist; cur; cur = cur->next) {
if (cur == this && cur->proc == curproc) {
*prev = cur->next;
if (cur->next) {
cur->next->when += this->when;
}
disposetimeout(this);
break;
}
prev = &cur->next;
}
}
/*
* timeout: called every 20 ms or so by GEMDOS, this routine
* is responsible for maintaining process times and such.
* it should also decrement the "proc_clock" variable, but
* should *not* take any action when it reaches 0 (the state of the
* stack is too uncertain, and time is too critical). Instead,
* a vbl routine checks periodically and if "proc_clock" is 0
* suspends the current process
*/
volatile int our_clock = 1000;
void ARGS_ON_STACK
timeout()
{
int ms; /* time between ticks */
ms = *((short *)0x442L);
if (proc_clock > 0)
proc_clock--;
our_clock -= ms;
if (tlist) {
tlist->when -= ms;
}
}
/*
* sleep() calls this routine to check on alarms and other sorts
* of time-outs on every context switch.
*/
void
checkalarms()
{
extern long searchtime; /* in dosdir.c */
PROC *p;
long delta;
void (*evnt) P_((PROC *));
TIMEOUT *old;
/* do the once per second things */
while (our_clock < 0) {
our_clock += 1000;
timestamp = Tgettime();
datestamp = Tgetdate();
searchtime++;
reset_priorities();
}
/* see if there are outstanding timeout requests to do */
while (tlist && ((delta = tlist->when) <= 0)) {
p = tlist->proc;
TRACE(("doing timeout code for pid %d", p->pid));
evnt = tlist->func;
old = tlist;
tlist = tlist->next;
disposetimeout(old);
/* call the timeout function */
(*evnt)(p);
/* if delta < 0, it's possible that the time has come for the next timeout
to occur */
if (tlist)
tlist->when += delta;
}
}
/*
* nap(n): nap for n milliseconds. Used in loops where we're waiting for
* an event. If we expect the event *very* soon, we should use yield
* instead.
* NOTE: we may not sleep for exactly n milliseconds; signals can wake
* us earlier, and the vagaries of process scheduling may cause us to
* oversleep...
*/
static void
unnapme(p)
PROC *p;
{
if (p->wait_q == SELECT_Q && p->wait_cond == (long)nap) {
short sr = spl7();
rm_q(SELECT_Q, p);
add_q(READY_Q, p);
spl(sr);
p->wait_cond = 0;
}
}
void ARGS_ON_STACK
nap(n)
unsigned n;
{
TIMEOUT *t;
t = addtimeout((long)n, unnapme);
sleep(SELECT_Q, (long)nap);
canceltimeout(t);
}